package com.imooc.bilibili.service;

import com.alibaba.fastjson.JSONObject;
import com.imooc.bilibili.dao.UserDao;
import com.imooc.bilibili.domain.PageResult;
import com.imooc.bilibili.domain.User;
import com.imooc.bilibili.domain.UserInfo;
import com.imooc.bilibili.domain.constant.UserConstant;
import com.imooc.bilibili.domain.exception.ConditionException;
import com.imooc.bilibili.util.MD5Util;
import com.imooc.bilibili.util.RSAUtil;
import com.imooc.bilibili.util.TokenUtil;
import com.mysql.cj.util.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * ProjectName imooc-bilibili
 *
 * @author xieyucan
 * <br>CreateDate 2022/10/21 18:02
 */
@Service
public class UserService {

    @Resource
    private UserDao userDao;

    @Resource
    private UserAuthService userAuthService;

    @Transactional
    public void addUser(User user) {
        String phone = user.getPhone();
        if(StringUtils.isNullOrEmpty(phone))
        {
            throw new ConditionException("手机号码不能为空");
        }
        User dbUser=this.getUserByPhone(phone);
        if(dbUser!=null){
            throw new ConditionException("该手机号码已经被注册了");
        }
        Date now = new Date();
        String salt = String.valueOf(now.getTime());
        //前端传递过来的密码(前端是经过加密的)
        String password = user.getPassword();
        //对前端加密的密码进行解码，然后再进行加密
        String rawPassword;
        try {
            rawPassword= RSAUtil.decrypt(password);
        }catch (Exception e){
            throw new ConditionException("密码解密失败");
        }
        String md5Password = MD5Util.sing(rawPassword, salt, "utf-8");
        user.setPassword(md5Password);
        user.setSalt(salt);
        user.setCreateTime(now);
        userDao.addUser(user);
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(user.getId());
        userInfo.setNick(UserConstant.DEFAULT_MICK);
        userInfo.setGender(UserConstant.GENDER_MALE);
        userInfo.setBirth(UserConstant.DEFAULT_BIRTH);
        userInfo.setCreateTime(now);
        userDao.addUserInfo(userInfo);
        //添加默认用户权限角色
        userAuthService.addUserDefaultRole(user.getId());
    }

    /**
     * 根据手机号码查询用户信息
     * @param phone
     * @return
     */
    public User getUserByPhone(String phone)
    {
        return userDao.getUserByPhone(phone);
    }

    public String login(User user) throws Exception {
        //查询手机号是否为空
        String phone = user.getPhone();
        if(StringUtils.isNullOrEmpty(phone))
        {
            throw new ConditionException("手机号码不能为空");
        }
        //查询手机号是否有用户
        User dbUser = this.getUserByPhone(phone);
        if(dbUser==null){
            throw new ConditionException("用户不存在");
        }
        //判断用户密码是否匹配  rsa解密  md5加密  然后进行匹配
        String password = user.getPassword();
        String rawPassword;
        try {
            rawPassword=RSAUtil.decrypt(password);
        }catch (Exception e){
            throw new ConditionException("密码解析失败");
        }
        String md5Password = MD5Util.sing(rawPassword, dbUser.getSalt(), "UTF-8");
        if(!md5Password.equals(dbUser.getPassword())){
            throw new ConditionException("密码输入错误");
        }
        //生成并且返回token令牌
        return TokenUtil.generateToken(dbUser.getId());
    }

    public User getUserInfo(Long userId)
    {
        User user = userDao.getUserById(userId);
        UserInfo userInfo = userDao.getUserInfoByUserId(userId);
        user.setUserInfo(userInfo);
        return user;
    }

    public void updateUserInfo(UserInfo userInfo) {
        userInfo.setUpdateTime(new Date());
        userDao.updateUserInfo(userInfo);
    }

    public void updateUser(User user) {
        user.setUpdateTime(new Date());
        userDao.updateUser(user);
    }

    public User getUserById(Long followingId) {
        return userDao.getUserById(followingId);
    }

    public List<UserInfo> getUserInfoByUserIds(Set<Long> followIdSet) {
        return userDao.getUserInfoByUserIds(followIdSet);
    }

    public PageResult<UserInfo> pageListUserInfo(JSONObject jsonObject) {
        Integer no = jsonObject.getInteger("no");
        Integer size = jsonObject.getInteger("size");
        jsonObject.put("start",(no-1)*size);
        jsonObject.put("limit",size);
        Integer total=userDao.pageCountUserInfo(jsonObject);
        List<UserInfo> userInfos = new ArrayList<>();
        if(total>0)
        {
            userInfos=userDao.pageListUserInfo(jsonObject);
        }
        return new PageResult<>(total,userInfos);
    }
}
